-------------------------------------------------------------------------------
-- Virtual Channel Admission Control: 
----------------------
-- Revisions:
-- 13.06.07: IPIDX_ARR bus (winning address bus) is now encoded binary instead of one hot.

library ieee;
 use ieee.std_logic_1164.all;
 use ieee.std_logic_unsigned.all;


library work;
 use work.router_pack.all;

-------------------------------------------------------------------------------
entity vcac is
-------------------------------------------------------------------------------
port( 
      -- General Control: --
      RESET      : in  std_logic;  -- Active Low 

      -- Interface to IPs: --
      H_ARR      : in  signaling_ssl_bus_type;
      
      -- Interface to OPs: --
      RH_ARR_MTX : out signaling_ssl_bus_type;  -- Post MUTEX header requests from all the VCs x IPs 
      IPIDX_ARR  : out vcac_idx_out_type;
      VC_BUSY    : in  std_logic_vector(num_of_vc_con-1 downto 0);
      H_VCS      : in  std_logic_vector(num_of_vc_con-1 downto 0)  -- HREQ from SSL-OP (to reset SPA)           
);           
-------------------------------------------------------------------------------
end vcac ;
-------------------------------------------------------------------------------

-------------------------------------------------------------------------------
architecture vcac_arch of vcac is
-------------------------------------------------------------------------------

component mutex_net_8
port( 
      -- MUTEX input i/f: --
      R       : in  std_logic_vector(mutex8_width_c-1 downto 0);

      -- MUTEX output i/f: --
      G       : out std_logic_vector(mutex8_width_c-1 downto 0)
);           
end component;

component spa
generic(
  SPA_WIDTH_G : integer := 2  -- Width of the SPA (number of request/grants)
);
port( 
      RESET   : in  std_logic;
 
      -- MUTEX input i/f: --
      R       : in  std_logic_vector(SPA_WIDTH_G-1 downto 0);
      EN      : in  std_logic; -- enable to start arbitration
      GATE    : in  std_logic; -- until is high no arbitration is done.
      
      -- MUTEX output i/f: --
      G       : out std_logic_vector(SPA_WIDTH_G-1 downto 0)           
);           
end component;

-- NOR (small)
COMPONENT nr02d1 -- drive x1
PORT(
  a1 : IN std_logic; 
  a2 : IN std_logic;
  zn : OUT std_logic
);
END COMPONENT;

component delay_line
generic(
   num_of_buffers : integer := 1
);
port( 
      DI  : in   std_logic;   
      DO  : out  std_logic   
);           
end component;

signal h_array :  std_logic_vector(mutex8_width_c-1 downto 0);

signal mtx_g_array :  std_logic_vector(mutex8_width_c-1 downto 0);
signal mtx_g :  signaling_ssl_bus_type;

signal spa_g :  std_logic_vector(num_of_vc_con-1 downto 0);
signal mtx_g_or, or_h_vcs : std_logic;

signal vc_busy_not : std_logic_vector(num_of_vc_con-1 downto 0);

signal mtx_g_bin : vc_op_idx_type; 

begin

-- 1. Input Mutex: 
u_mutex_net_8: mutex_net_8
port map( 
      R  => h_array,  

      G  => mtx_g_array 
); 

h_array <= H_ARR(1) & H_ARR(0);
mtx_g(0) <= mtx_g_array(3 downto 0);
mtx_g(1) <= mtx_g_array(7 downto 4);

-- 1a. Header Request delay element to match the long delay of the wide OR on MUTEX outs: --
delay_line_head_out_gen: for i in 0 to (num_of_ports_con-1) generate

 u_delay_line_header_vc0: delay_line
 generic map(
   num_of_buffers => 2
 )
 port map( 
      DI  => mtx_g(0)(i),    
      DO  => RH_ARR_MTX(0)(i) 
 );  
 
 u_delay_line_header_vc1: delay_line
 generic map(
   num_of_buffers => 2
 )
 port map( 
      DI  => mtx_g(1)(i),    
      DO  => RH_ARR_MTX(1)(i) 
 );           

end generate;

-- 2. OR on MUTEX Grants:
mtx_g_or <= mtx_g_array(7) or mtx_g_array(6) or mtx_g_array(5) or mtx_g_array(4) or 
            mtx_g_array(3) or mtx_g_array(2) or mtx_g_array(1) or mtx_g_array(0);


-- 2a. Invert BUSY line:
nor_vc_gen: for i in 0 to (num_of_vc_con-1) generate
  u_busy_not: nr02d1
  port map(
      a1 => RESET,
      a2 => VC_BUSY(i),
      zn => vc_busy_not(i)
  );
end generate;

-- 3. SPA
u_spa: spa
port map( 
      RESET  => RESET,

      R      => vc_busy_not,
      EN     => mtx_g_or,
      
      GATE   => or_h_vcs,

      G      => spa_g
);   


-- 4. Binary encoding from one-hot: --
one_hot2bin_proc: process (mtx_g_array)
begin
--variable code: std_logic_vector(binary'RANGE);
--begin
--  code := (others => '0');
--  for N in onehot'RANGE loop
--  if onehot(N) = '1' then
--  code := code OR std_logic_vector(to_unsigned(N, code'LENGTH));
--  end if;
--  end loop;
--  binary <= code;

 case mtx_g_array is
  when "00000001" =>
   mtx_g_bin <= 0;
  when "00000010" =>
   mtx_g_bin <= 1;
  when "00000100" =>
   mtx_g_bin <= 2;
  when "00001000" =>
   mtx_g_bin <= 3;
  when "00010000" =>
   mtx_g_bin <= 4;
  when "00100000" =>
   mtx_g_bin <= 5;
  when "01000000" =>
   mtx_g_bin <= 6;
  when "10000000" =>
   mtx_g_bin <= 7; 
  when others =>
   mtx_g_bin <= 8;
 end case;
end process;
  
  
-- 5: MUX on IP index
vcac_mux_idx_proc: process(spa_g, mtx_g_bin) --mtx_g)
begin
 -- Default: --
 --IPIDX_ARR <= (others=>(others=>(others=>'0')));
  IPIDX_ARR <= (others=>8); -- MSB=1, invalid.

 case spa_g is
  when "01" =>
    IPIDX_ARR(0) <= mtx_g_bin; --mtx_g; -- send the index to VC0
  when "10" =>
    IPIDX_ARR(1) <= mtx_g_bin; --mtx_g; -- send the index to VC1
  when others =>
    NULL;
 end case; 

end process;

-- 5. OR on H-requests from SSL-OPs
or_h_vcs <= H_VCS(1) or H_VCS(0);

-------------------------------------------------------------------------------
end vcac_arch;
-------------------------------------------------------------------------------                 

   
-------------------------------------------------------------------------------
configuration  vcac_cfg  of vcac is
-------------------------------------------------------------------------------
   for vcac_arch
   end for;
-------------------------------------------------------------------------------
end  vcac_cfg;              
-------------------------------------------------------------------------------
                 
